Any device driver that performs uncached writes to main memory must always do writes in 8-byte quantities.[19] If the driver needs to write a smaller piece of memory, then it must do the write as a read-modify-write operation of an 8-byte piece of memory. For example, a driver with code like the following (assuming that the structure is being accessed uncached), would corrupt memory:
struct foo_s { char b0; char b1; char b2; char b3; char b4; char b5; char b6; char b7; } bar1; driver_write_bar1_b3 () { bar1.b3 = 5; }Instead, it would have to be modified to perform a read-modify-write operation on the whole double-word containing b3, as in the following example (on a big-endian system):
struct foo_s { union { __uint64 dw; /* A 64-bit quantity */ struct { char b0; /* READ ONLY */ char b1; /* READ ONLY */ char b2; /* READ ONLY */ char b3; /* READ ONLY */ char b4; /* READ ONLY */ char b5; /* READ ONLY */ char b6; /* READ ONLY */ char b7; /* READ ONLY */ } byte; } dw0; } bar1; driver_write_bar1_b3 () { bar1.dw0.dw = (bar1.dw0.dw & ~(0xff<<32)) | (5<<32); }If at all possible, use cached accesses to memory, along with cache coherency operations where necessary, instead of uncached operations. Cache coherency operations are necessary only for data shared by the CPU and a device that needs to perform DMA. See "Data Cache Write Back and Invalidation" for more information on use of cache coherency operations.